from tablestore import *
import time

class FooderTableStoreError(RuntimeError):
    def __init__(self, errMsg):
        self.errMsg = errMsg

    def data(self, errDetails):
        self.errDetails = errDetails
        return self

ErrTableStoreRuntime = FooderTableStoreError("TableStore Runtime Error")
ErrTableStoreOTSClient = FooderTableStoreError("refresh_init OTSClient Error")

class TableUtil:
    def __init__(self, endpoint, instance_name, context):
        if endpoint is None or \
            instance_name is None or\
            context is None:
            raise RuntimeError('param has None')
        self.endpoint = endpoint
        self.instance_name = instance_name
        self.refresh_init(context)

    # 重新初始化
    def refresh_init(self, context):
        cred = context.credentials
        self.table_client = OTSClient(self.endpoint,
                                      cred.access_key_id,
                                      cred.access_key_secret,
                                      self.instance_name,
                                      sts_token=cred.security_token)

    # 获取实例下所有表的表名
    def get_table_list(self, context):
        if self.table_client is None:
            self.refresh_init(context)
        if self.table_client is not None:
            list_response = self.table_client.list_table()
            return list_response
        return None

    def put_row_dishInfo_noImg(self, context, shopId, dishName, primary_key, attribute_columns):
        '''
        插入一条菜品信息（无图）
        eg: primary_key = [('shopId', '商家A'), ('dishId', '')]
            attribute_columns = [('dishName', '爆炒土豆丝'), ('dishPrice', 1200), 
                                    ('dishTmpPrice', 1200), ('goodsType', 1=菜品/2=酒水)]
        '''
        if self.table_client is None:
            self.refresh_init(context)
        if self.table_client is None:
            raise ErrTableStoreOTSClient
        try:
            # 多元索引多条件组合查询，查询dishName是否已存在
            bool_query = BoolQuery(must_queries=[
                TermQuery('shopId', shopId),
                TermQuery('dishName', dishName)
            ])
            search_response = self.table_client.search('dish_list', 'shopId_dishName_index',
                SearchQuery(bool_query, limit=2, get_total_count=True),
                ColumnsToGet()
            )
            if search_response.total_count <= 0:
                # dishName不存在则创建
                t = str(round(time.time()*1000))
                attribute_columns.append(('createTime', t))
                attribute_columns.append(('updateTime', t))
                row = Row(primary_key, attribute_columns)
                self.table_client.put_row('dish_list', row)
        except Exception as e:
            raise ErrTableStoreRuntime.data(str(e))

    def put_row_dishInfo_Img(self, context, shopId, dishName, primary_key, attribute_columns):
        '''
        插入一条菜品信息（有图）
        eg: primary_key = [('shopId', '商家A'), ('dishId', '')]
            attribute_columns = [('dishName', '爆炒土豆丝'), ('dishPrice', 1200), ('dishTmpPrice', 1200), ('goodsType', 1=菜品/2=酒水)]
        return: 'exist'/'suc'/'fail'
        '''
        if self.table_client is None:
            self.refresh_init(context)
        if self.table_client is None:
            raise ErrTableStoreOTSClient
        try:
            # 多元索引多条件组合查询，查询dishName是否已存在
            bool_query = BoolQuery(must_queries=[
                TermQuery('shopId', shopId),
                TermQuery('dishName', dishName)
            ])
            search_response = self.table_client.search('dish_list', 'shopId_dishName_index',
                SearchQuery(bool_query, limit=1, get_total_count=False),
                ColumnsToGet()
            )
            rows = search_response.rows
            dishId = None
            if len(rows) > 0:
                # 已存在获取dishId
                dishId = rows[0][0][1][1]
            else:
                t = str(round(time.time()*1000))
                attribute_columns.append(('createTime', t))
                attribute_columns.append(('updateTime', t))
                row = Row(primary_key, attribute_columns)
                self.table_client.put_row('dish_list', row)
        except Exception as e:
            raise ErrTableStoreRuntime.data(str(e))

        return dishId

    def delete_row_dishInfo(self, context, primary_key):
        '''
        删除一条菜品信息，返回True/False 
        eg: primary_key = [('shopId', '商家A'), ('dishId', '')]
        '''
        if self.table_client is None:
            self.refresh_init(context)
        if self.table_client is None:
            raise ErrTableStoreOTSClient
        try:
            row = Row(primary_key)
            self.table_client.delete_row('dish_list', row)
        except Exception as e:
            raise ErrTableStoreRuntime.data(str(e))

    def put_row_feaInfo(self, context, primary_key, attribute_columns):
        '''
        插入一条菜品特征信息，返回True/False 
        eg: primary_key = [('shopId', '商家A'), ('feaId', ''), ('dishId', '')]
            attribute_columns = [('fea', dictSerializToStr(oneFea)), ('feaImgUrl', 'shopId/feaId.jpg')]
        '''
        if self.table_client is None:
            self.refresh_init(context)
        if self.table_client is None:
            raise ErrTableStoreOTSClient
        try:
            t = str(round(time.time() * 1000))
            attribute_columns.append(('createTime', t))
            attribute_columns.append(('updateTime', t))
            row = Row(primary_key, attribute_columns)
            self.table_client.put_row('dish_fea_list', row)
        except Exception as e:
            raise ErrTableStoreRuntime.data(str(e))

    def delete_row_feaInfo(self, context, primary_key):
        '''
        删除一条菜品特征信息，返回True/False 
        eg: primary_key = [('shopId', '商家A'), ('feaId', ''), ('dishId', '')]
        '''
        if self.table_client is None:
            self.refresh_init(context)
        if self.table_client is None:
            raise ErrTableStoreOTSClient
        try:
            row = Row(primary_key)
            self.table_client.delete_row('dish_fea_list', row)
        except Exception as e:
            raise ErrTableStoreRuntime.data(str(e))

    def put_row_menuInfo(self, context, primary_key, attribute_columns):
        '''
        插入一条菜单信息，返回True/False 
        eg: primary_key = [('shopId', '商家A'), ('taleId', '')]
            attribute_columns = [('taleName', '')]
        '''
        if self.table_client is None:
            self.refresh_init(context)

        if self.table_client is not None:
            table_name = 'dish_fea_list'
            primary_key.append('codeType', 'menulist')
            t = str(round(time.time() * 1000))
            attribute_columns.append(('createTime', t))
            attribute_columns.append(('updateTime', t))
            row = Row(primary_key, attribute_columns)
            self.table_client.put_row(table_name, row)
            return True
        return False

    def delete_row_menuInfo(self, context, primary_key):
        '''
        删除一条菜单信息，返回True/False 
        eg: primary_key = [('shopId', '商家A'), ('taleId', '')]
        '''
        if self.table_client is None:
            self.refresh_init(context)

        if self.table_client is not None:
            table_name = 'dish_fea_list'
            primary_key.append('codeType', 'menulist')
            row = Row(primary_key)
            self.table_client.delete_row(table_name, row)
            return True
        return False

    def put_row_classInfo(self, context, primary_key, attribute_columns):
        '''
        插入一条菜品类别信息，返回True/False 
        eg: primary_key = [('shopId', '商家A'), ('taleId', '')]
            attribute_columns = [('taleName', '')]
        '''
        if self.table_client is None:
            self.refresh_init(context)

        if self.table_client is not None:
            table_name = 'dish_fea_list'
            primary_key.append('codeType', 'classlist')
            t = str(round(time.time() * 1000))
            attribute_columns.append(('createTime', t))
            attribute_columns.append(('updateTime', t))
            row = Row(primary_key, attribute_columns)
            self.table_client.put_row(table_name, row)
            return True
        return False

    def delete_row_classInfo(self, context, primary_key):
        '''
        删除一条菜品类别信息，返回True/False 
        eg: primary_key = [('shopId', '商家A'), ('taleId', '')]
        '''
        if self.table_client is None:
            self.refresh_init(context)

        if self.table_client is not None:
            table_name = 'dish_fea_list'
            primary_key.append('codeType', 'classlist')
            row = Row(primary_key)
            self.table_client.delete_row(table_name, row)
            return True
        return False

    def get_dish_details(self, context, shopId, dishId):
        '''
        根据商家Id、dishId查询菜品详情信息
        return:
            { 
                'dishId': '',
                'dishName': '',
                'createTime': '1627740924956',
                'updateTime': '1627740924956',
                'dishPrice': 1200,
                'dishes': [
                    {
                        'feaId': '', 
                        'feaImgUrl': 'oss url', 
                        'createTime': '1627740924969', 
                        'updateTime': '1627740924969'
                    }
                ]
            }
        '''
        if self.table_client is None:
            self.refresh_init(context)

        if self.table_client is not None:
            primary_key = [('shopId', shopId), ('dishId', dishId)]
            columns_to_get = [
                'dishName', 'dishPrice', 'createTime', 'updateTime'
            ]
            _, return_row, _ = self.table_client.get_row(
                'dish_list', primary_key, columns_to_get, None, 1)
            dishInfo = {
                'dishId': dishId,
                'dishName': '',
                'createTime': '',
                'updateTime': '',
                'dishes': []
            }
            for x in return_row.attribute_columns:
                if x[0] == 'dishName':
                    dishInfo['dishName'] = x[1]
                if x[0] == 'dishPrice':
                    dishInfo['dishPrice'] = x[1]
                if x[0] == 'createTime':
                    dishInfo['createTime'] = x[1]
                if x[0] == 'updateTime':
                    dishInfo['updateTime'] = x[1]
            # 多条件组合查询
            bool_query = BoolQuery(must_queries=[
                TermQuery('shopId', shopId),
                TermQuery('dishId', dishId)
            ])
            # 多元索引
            search_response = self.table_client.search(
                'dish_fea_list', 'shopId_dishId_index',
                SearchQuery(bool_query, limit=100, get_total_count=True),
                ColumnsToGet(return_type=ColumnReturnType.ALL))
            dishes = []
            for feas in search_response.rows:
                dish = {
                    'feaId': '',
                    'feaImgUrl': '',
                    'createTime': '',
                    'updateTime': ''
                }
                for fea in feas:
                    for x in fea:
                        if x[0] == 'feaId':
                            dish['feaId'] = x[1]
                        if x[0] == 'feaImgUrl':
                            dish['feaImgUrl'] = x[1]
                        if x[0] == 'createTime':
                            dish['createTime'] = x[1]
                        if x[0] == 'updateTime':
                            dish['updateTime'] = x[1]
                dishes.append(dish)
            dishInfo['dishes'] = dishes
        return None, None

    def get_dishInfoByDishId(self, context, primary_key):
        '''
        根据菜品Id获取菜品信息
        eg: primary_key = [('shopId', '商家A'), ('dishId', '')]
        '''
        if self.table_client is None:
            self.refresh_init(context)
        if self.table_client is None:
            raise ErrTableStoreOTSClient
        try:
            columns_to_get = ['dishName', 'dishPrice']
            _, return_row, _ = self.table_client.get_row('dish_list', primary_key, columns_to_get, None, 1)
            return return_row.attribute_columns[0][1], return_row.attribute_columns[1][1]
        except Exception as e:
            raise ErrTableStoreRuntime.data(str(e))


    def get_MatchAllQuery12(self, context, table_name, index_name, shopId='商家A'):
        '''
        匹配所有行查询
        '''
        if self.table_client is None:
            self.refresh_init(context)

        query = MatchPhraseQuery('shopId', shopId)
        if self.table_client is not None:
            all_rows, next_token = [], None
            while not all_rows or next_token:
                search_response = self.table_client.search(
                    table_name,
                    index_name,
                    SearchQuery(query,
                                next_token=next_token,
                                limit=100,
                                get_total_count=True),
                    columns_to_get=ColumnsToGet(
                        return_type=ColumnReturnType.ALL))
                all_rows.extend(search_response.rows)
            for row in all_rows:
                print('row=====', row)
            return all_rows
        return None

    def get_rowList(self, context, table_name, index_name, query):
        if self.table_client is None:
            self.refresh_init(context)

        if self.table_client is not None:
            all_rows, next_token = [], None
            while not all_rows or next_token:
                rows, next_token, total_count, is_all_succeed = self.table_client.search(
                    table_name, index_name,
                    SearchQuery(query, limit=100, get_total_count=True),
                    ColumnsToGet(return_type=ColumnReturnType.ALL))
                all_rows.extend(rows)
            return all_rows
        return None